package code

import (
	"errors"
	"fmt"
)

// error介绍
type User struct {
	Name string
}

func gen() (*User, error) {
	return nil, errors.New("user == nil")
}

func Error01() {
	if user, err := gen(); err != nil {
		fmt.Println("error:", err)
		return
	} else {
		fmt.Println("user-name:", user.Name)
	}
}

// error 的使用
var MoneyNotEnough = errors.New("money not enough")

func pay(money float64) error {
	if money < 20 {
		// return errors.New("money not enough")
		// return MoneyNotEnough
		// fmt.Errorf("money not enough, you have %f", money) == errors.New("money not enough")
		return fmt.Errorf("money not enough, you have %f", money)
	}
	return nil
}

func Error02() {
	if err := pay(10); errors.Is(err, MoneyNotEnough) {
		fmt.Println("错误 是 余额不足")
	} else {
		fmt.Println("错误 不是 余额不足")
	}
}

// error 转换为具体的error类型: errors.As
type MyError struct {
	Msg string
}

func (e *MyError) Error() string {
	return e.Msg
}

var MoneyNotEnough3 = &MyError{"money not enough"}

func pay3(money float64) error {
	if money < 20 {
		return MoneyNotEnough3
	}
	return nil
}

func Error03() {
	err := pay3(10)
	var myError *MyError
	if errors.As(err, &myError) {
		fmt.Println("转换成功")
		fmt.Println(myError.Error())
	} else {
		fmt.Println("不是此error类型")
	}
}

// 错误进行封装, 封装后的错误和之前相等: fmt.Errorf
func Error04() {
	originErr := errors.New("origin error")
	// %w 嵌套生成一个新的错误
	newErr := fmt.Errorf("wrap error: %w", originErr)
	if errors.Is(newErr, originErr) {
		fmt.Println("newErr is originErr")
	}

	// 用于一个错误对象展开, 得到下一层错误对象
	originErr2 := errors.Unwrap(newErr)
	if errors.Is(originErr2, originErr) {
		fmt.Println("originErr2 is originErr")
	}
}

// 多个错误的封装, 这是go1.20的新特性: errors.Join
func Error05() {
	err1 := errors.New("error1")
	err2 := errors.New("error2")
	err3 := errors.New("error3")
	err := errors.Join(err1, err2, err3)
	if errors.Is(err, err1) {
		fmt.Println("err is err1")
	}

	if errors.Is(err, err2) {
		fmt.Println("err is err2")
	}
}
